use std::{env, time::Duration};

use sea_orm::{ConnectOptions, Database, DatabaseConnection};
use tokio::sync::OnceCell;

static DB_CLIENT: OnceCell<DatabaseConnection> = OnceCell::const_new();

pub async fn establish_connection() -> DatabaseConnection {
    DB_CLIENT
        .get_or_init(|| async {
            let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
            let mut opt = ConnectOptions::new(database_url);
            opt.max_connections(100)
            .min_connections(5)
            .connect_timeout(Duration::from_secs(8))
            .acquire_timeout(Duration::from_secs(8))
            .idle_timeout(Duration::from_secs(8))
            .max_lifetime(Duration::from_secs(8))
            .sqlx_logging(true)
            .sqlx_logging_level(log::LevelFilter::Info)
            .set_schema_search_path("my_schema"); // Setting default PostgreSQL schema
            Database::connect(opt).await.expect("Failed to connect to database")
        })
        .await.clone()
}

#[cfg(test)]
mod tests {
    use dotenvy::dotenv;
    use migration::{Migrator, MigratorTrait};
    use sea_orm::{ActiveModelTrait, EntityTrait, Set};
    use ysbase::func::short_id;

    use crate::task_record::{self, Model, TriggerType};

    use super::establish_connection;

    #[tokio::test]
    async fn test_migration() {
        dotenv().ok(); // Load .env file
        let db = establish_connection().await;
        Migrator::up(&db, None).await.expect("Failed to run migrations");
    }

    #[tokio::test]
    async fn test_connection() {
        dotenv().ok(); // Load .env file
        let db = establish_connection().await;
        assert!(db.ping().await.is_ok());
        let _ = db.clone().close().await;
        //assert!(matches!(db.ping().await, Err(DbErr::ConnectionAcquire)));
    }

    #[tokio::test]
    async fn test_insert() -> Result<(), sea_orm::DbErr> {
        dotenv().ok(); // Load .env file
        let db = establish_connection().await;

        let id = short_id();
        
        let pear = task_record::ActiveModel {
            id: Set(id.to_string()),
            name: Set("Pear".to_owned()),
            trigger_type: Set(TriggerType::Cron),
            trigger_expr: Set("*/10 * * * * ?".to_owned()),
            action_type: Set("ring".to_owned()),
            action_expr: Set("10".to_owned()),
            is_finish: Set(false),
        };
        let _data = task_record::Entity::insert(pear).exec(&db).await?;

        // 尝试查询插入的记录
        let found_pear = task_record::Entity::find_by_id(id).one(&db).await?;
        assert!(found_pear.is_some(), "Inserted item not found"); // 确保记录存在
        Ok(())
    }
}